home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / windows5 / winsrc17.zip / DIALOG.C < prev    next >
C/C++ Source or Header  |  1991-12-05  |  20KB  |  701 lines

  1. /*
  2.  
  3.     various dialog-box code - there's more in DIALOG2.C
  4.  
  5. */
  6.  
  7. #include "windows.h"
  8. #include "winfract.h"
  9. #include "mathtool.h"
  10. #include "fractint.h"
  11. #include <string.h>
  12. #include <math.h>
  13. #include <stdio.h>
  14. #include <sys\types.h>
  15. #include <sys\stat.h>
  16.  
  17. extern HWND hwnd;                               /* handle to main window */
  18. extern char szHelpFileName[];            /* Help file name*/
  19. extern HANDLE hThisInst;
  20.  
  21. extern LPBITMAPINFO pDibInfo;
  22. extern char huge *pixels;
  23. extern LPLOGPALETTE pLogPal;
  24.  
  25. char FullPathName[128];
  26. char DialogTitle[128];
  27. char FileName[128];
  28. char PathName[128];
  29. char OpenName[128];
  30. char DefPath[128];
  31. char DefSpec[13];
  32. char DefExt[10];
  33. char str[255];
  34. BOOL OperCancelled;
  35.  
  36. OFSTRUCT OfStruct;              /* information from OpenFile()     */
  37. struct stat FileStatus;           /* information from fstat()       */
  38.  
  39.  
  40. /****************************************************************************
  41.  
  42.     FUNCTION: SaveAsDlg(HWND, unsigned, WORD, LONG)
  43.  
  44.     PURPOSE: Allows user to change name to save file to
  45.  
  46.     COMMENTS:
  47.  
  48.     This will initialize the window class if it is the first time this
  49.     application is run.  It then creates the window, and processes the
  50.     message loop until a PostQuitMessage is received.  It exits the
  51.     application by returning the value passed by the PostQuitMessage.
  52.  
  53. ****************************************************************************/
  54.  
  55. BOOL bSaveEnabled = FALSE;
  56.  
  57. extern int time_to_save;
  58. extern int gif87a_flag;
  59. int FileFormat = 0;
  60. FARPROC lpStatusBox = NULL;
  61. HWND hStatusBox;
  62. char StatusTitle[80];
  63.  
  64. BOOL FAR PASCAL StatusBoxProc(HWND hDlg, unsigned Msg, WORD wParam,
  65.                 LONG lParam)
  66. {
  67.    char PerStr[10];
  68.    RECT Rect, TextRect;
  69.    HWND hBar, hCancel;
  70.    HDC hBarDC;
  71.    unsigned Percent;
  72.  
  73.    switch(Msg)
  74.    {
  75.       case WM_INITDIALOG:
  76.          SetWindowText(hDlg, StatusTitle);
  77.          hCancel = GetDlgItem(hDlg, ID_CANCEL);
  78.          SetFocus(hCancel);
  79.          return(FALSE);
  80.  
  81.       case WM_CHAR:
  82.          if(wParam == VK_RETURN || wParam == VK_ESCAPE)
  83.             OperCancelled = TRUE;
  84.          break;
  85.  
  86.       case WM_COMMAND:
  87.          if(wParam == ID_CANCEL)
  88.             OperCancelled = TRUE;
  89.          break;
  90.  
  91.       case WM_USER:
  92.          /* Invalidate Bar Window */
  93.          hBar = GetDlgItem(hDlg, ID_PERCENT);
  94.          GetClientRect(hBar, &TextRect);
  95.  
  96.          /* Calculate Percentage */
  97.          hBarDC = GetDC(hBar);
  98.          Percent = (unsigned)((lParam * 100) / wParam);
  99.          if(Percent <= 100)
  100.          {
  101.             wsprintf(PerStr, "%d", Percent);
  102.             strcat(PerStr, "%");
  103.  
  104.             /* Display Bar */
  105.             Rect = TextRect;
  106.             Rect.right = (unsigned)((((long)Percent) * Rect.right) / 100);
  107.             Rect.top += 2;
  108.             Rect.bottom -= 2;
  109.             Rectangle(hBarDC, Rect.left, Rect.top, Rect.right, Rect.bottom);
  110.  
  111.             /* Display Percentage */
  112.             DrawText(hBarDC, PerStr, lstrlen(PerStr), &TextRect,
  113.                      DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  114.          }
  115.  
  116.          ReleaseDC(hBar, hBarDC);
  117.          break;
  118.  
  119.       case WM_DESTROY:
  120.          break;
  121.  
  122.       default:
  123.          return(FALSE);
  124.    }
  125.    return(TRUE);
  126. }
  127.  
  128. void OpenStatusBox(HWND hWnd, HANDLE hInst)
  129. {
  130.    if(lpStatusBox == NULL)
  131.       lpStatusBox = MakeProcInstance(StatusBoxProc, hInst);
  132.    hStatusBox = CreateDialog(hInst, "StatusBox", hWnd, lpStatusBox);
  133. }
  134.  
  135. void CloseStatusBox(void)
  136. {
  137.    DestroyWindow(hStatusBox);
  138. }
  139.  
  140. void UpdateStatusBox(unsigned long Partial, unsigned long Total)
  141. {
  142.    if(Total > 0xffff)
  143.    {
  144.       Total >>= 16;
  145.       Partial >>= 16;
  146.    }
  147.    SendMessage(hStatusBox, WM_USER, (unsigned)Total, Partial);
  148. }
  149.  
  150. void AddFormatExt(void)
  151. {
  152.    unsigned n;
  153.    char *ExtStr;
  154.  
  155.    if(FileFormat == ID_BMP)
  156.       ExtStr = ".BMP";
  157.    else
  158.       ExtStr = ".GIF";
  159.    for(n = 0; FileName[n] && FileName[n] != '.'; n++);
  160.    strcpy(&FileName[n], ExtStr);
  161. }
  162.  
  163. void UpdateDefPath(HWND hDlg)
  164. {
  165.    unsigned char TempName[128];
  166.    int n;
  167.  
  168.    GetDlgItemText(hDlg, IDC_EDIT, TempName, sizeof(TempName));
  169.    for(n = lstrlen(TempName) - 1; n >= 0; n--)
  170.    {
  171.       if(TempName[n] == '\\')
  172.       {
  173.          HWND hEdit;
  174.  
  175.          strcpy(FileName, &TempName[n+1]);
  176.          hEdit = GetDlgItem(hDlg, IDC_EDIT);
  177.          SetWindowText(hEdit, FileName);
  178.          TempName[n] = 0;
  179.          DlgDirList(hDlg, TempName, NULL, IDC_PATH, 0x4010);
  180.          GetDlgItemText(hDlg, IDC_PATH, DefPath, sizeof(FullPathName));
  181.          break;
  182.       }
  183.    }
  184.    if(n < 0)
  185.       strcpy(FileName, TempName);
  186.    FileName[8] = 0;
  187.    AddFormatExt();
  188. }
  189.  
  190.  
  191. BOOL Check4Wildcards(hWnd, pSrc)
  192. HWND hWnd;
  193. PSTR pSrc;
  194. {
  195.     PSTR pTmp;
  196.  
  197.     if (!pSrc[0])
  198.     return (FALSE);           /* Indicates no filename was specified */
  199.  
  200.     pTmp = pSrc;
  201.     while (*pTmp) {            /* Searches the string for wildcards */
  202.     switch (*pTmp++) {
  203.         case '*':
  204.         case '?':
  205.         MessageBox(hWnd, "Wildcards not allowed.",
  206.             NULL, MB_OK | MB_ICONEXCLAMATION);
  207.         return (FALSE);
  208.     }
  209.     }
  210.     return(TRUE);
  211. }
  212.  
  213. int FAR PASCAL SaveAsDlg(hDlg, message, wParam, lParam)
  214. HWND hDlg;
  215. unsigned message;
  216. WORD wParam;
  217. LONG lParam;
  218. {
  219.     unsigned char TempName[128];
  220.  
  221.     switch (message) {
  222.  
  223.      case WM_KEYDOWN:
  224.          switch (wParam) {
  225.          case VK_F1:
  226.          /* F1, shifted F1 bring up the Help Index */
  227.              WinHelp(hwnd,szHelpFileName,HELP_INDEX,0L);
  228.              break;
  229.          }
  230.  
  231.     case WM_INITDIALOG:
  232.  
  233.         SetDlgItemText(hDlg, ID_FILETITLE, DialogTitle);
  234.             AddFormatExt();
  235.             while(OpenFile(FileName, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0)
  236.                updatesavename(FileName);
  237.  
  238.         EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled);
  239.  
  240.             if(FileFormat == 0)
  241.                FileFormat = (gif87a_flag) ? ID_GIF87A : ID_GIF89A;
  242.             CheckDlgButton(hDlg, FileFormat, 1);
  243.             SetDlgItemText(hDlg, IDC_EDIT, FileName);
  244.         SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  245.             UpdateDefPath(hDlg);
  246.             if(DefPath[0] == 0)
  247.             {
  248.                DlgDirList(hDlg, "*.*", NULL, IDC_PATH, 0x4010);
  249.                GetDlgItemText(hDlg, IDC_PATH, DefPath, sizeof(FullPathName));
  250.             }
  251.         SendDlgItemMessage(hDlg, IDC_EDIT, EM_SETSEL, 0,
  252.             MAKELONG(0, 0x7fff));
  253.  
  254.         return (FALSE);            /* FALSE since Focus was changed */
  255.  
  256.     case WM_COMMAND:
  257.         switch (wParam) {
  258.             /* MCP 10-27-91, Update file format */
  259.                 case ID_GIF87A:
  260.                 case ID_GIF89A:
  261.                 case ID_BMP:
  262.                    CheckDlgButton(hDlg, FileFormat, 0);
  263.                    FileFormat = wParam;
  264.                    CheckDlgButton(hDlg, FileFormat, 1);
  265.                    gif87a_flag = (wParam == ID_GIF87A);
  266.                    GetDlgItemText(hDlg, IDC_EDIT, FileName, 128);
  267.                    AddFormatExt();
  268.                    SetDlgItemText(hDlg, IDC_EDIT, FileName);
  269.                    return(TRUE);
  270.  
  271.         case IDC_EDIT:
  272.  
  273.             /* If there was previously no filename in the edit
  274.              * control, then the save control must be enabled as soon as
  275.              * a character is entered.
  276.              */
  277.  
  278.             if (HIWORD(lParam) == EN_CHANGE && !bSaveEnabled)
  279.                  EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled = TRUE);
  280.                     else if(HIWORD(lParam) == EN_KILLFOCUS)
  281.                        UpdateDefPath(hDlg);
  282.  
  283.                     return (TRUE);
  284.  
  285.         case IDOK:
  286.  
  287.            /* Get the filename from the edit control */
  288.  
  289.             GetDlgItemText(hDlg, IDC_EDIT, TempName, 128);
  290.  
  291.             /* If there are no wildcards, then separate the name into
  292.              * path and name.  If a path was specified, replace the
  293.              * default path with the new path.
  294.              */
  295.  
  296.                     UpdateDefPath(hDlg);
  297.                     strcpy(FullPathName, DefPath);
  298.                     strcat(FullPathName, "\\");
  299.                     strcat(FullPathName, FileName);
  300.                 SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  301.                     SendDlgItemMessage(hDlg, IDC_EDIT, EM_SETSEL, 0,
  302.                MAKELONG(0, 0x7fff));
  303.             if (Check4Wildcards(hDlg, FullPathName)) {
  304.                         if (OpenFile(FullPathName, (LPOFSTRUCT) &OfStruct,
  305.                            OF_EXIST) >= 0)
  306.                         {
  307.                         sprintf(str, "Replace existing %s?", FullPathName);
  308.                         if (MessageBox(hDlg, str, "Save . . .",
  309.                        MB_YESNO | MB_ICONQUESTION) == IDNO)
  310.                                return(TRUE);
  311.                         }
  312.  
  313.                          /* Tell the caller a filename was selected */
  314.                EndDialog(hDlg, IDOK);
  315.                time_to_save = 1;
  316.                        OperCancelled = FALSE;
  317.                     }
  318.             return(TRUE);
  319.  
  320.         case IDCANCEL:
  321.  
  322.             /* Tell the caller the user canceled the SaveAs function */
  323.  
  324.             EndDialog(hDlg, IDCANCEL);
  325.             time_to_save = 0;
  326.             return (TRUE);
  327.         }
  328.         break;
  329.  
  330.     }
  331.     return (FALSE);
  332. }
  333.  
  334. /****************************************************************************
  335.  
  336.     FUNCTION: OpenDlg(HWND, unsigned, WORD, LONG)
  337.  
  338.     PURPOSE: Let user select a file, and return.  Open code not provided.
  339.  
  340. ****************************************************************************/
  341.  
  342. HANDLE FAR PASCAL OpenDlg(hDlg, message, wParam, lParam)
  343. HWND hDlg;
  344. unsigned message;
  345. WORD wParam;
  346. LONG lParam;
  347. {
  348.     HANDLE hFile=1;    /* Temp value for return */
  349.  
  350.     switch (message) {
  351.  
  352.     case WM_KEYDOWN:
  353.         switch (wParam) {
  354.         case VK_F1:
  355.         /* F1, shifted F1 bring up the Help Index */
  356.             WinHelp(hwnd,szHelpFileName,HELP_INDEX,0L);
  357.             break;
  358.         }
  359.  
  360.     case WM_COMMAND:
  361.         switch (wParam) {
  362.  
  363.         case IDC_LISTBOX:
  364.             switch (HIWORD(lParam)) {
  365.  
  366.             case LBN_SELCHANGE:
  367.                 /* If item is a directory name, append "*.*" */
  368.                 if (DlgDirSelect(hDlg, str, IDC_LISTBOX))
  369.                 strcat(str, DefSpec);
  370.  
  371.                 SetDlgItemText(hDlg, IDC_EDIT, str);
  372.                 SendDlgItemMessage(hDlg,
  373.                 IDC_EDIT,
  374.                 EM_SETSEL,
  375.                 NULL,
  376.                 MAKELONG(0, 0x7fff));
  377.                 break;
  378.  
  379.             case LBN_DBLCLK:
  380.                 goto openfile;
  381.             }
  382.             return (TRUE);
  383.  
  384.         case IDOK:
  385. openfile:
  386.             GetDlgItemText(hDlg, IDC_EDIT, OpenName, 128);
  387.             if (strchr(OpenName, '*') || strchr(OpenName, '?')) {
  388.             SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
  389.                 (LPSTR) OpenName);
  390.             if (str[0])
  391.                 strcpy(DefPath, str);
  392.             ChangeDefExt(DefExt, DefSpec);
  393.             UpdateListBox(hDlg);
  394.             return (TRUE);
  395.             }
  396.  
  397.             if (!OpenName[0]) {
  398.             MessageBox(hDlg, "No filename specified.",
  399.                 NULL, MB_OK | MB_ICONHAND);
  400.             return (TRUE);
  401.             }
  402.  
  403.             AddExt(OpenName, DefExt);
  404.             strcpy(FileName, OpenName);
  405.  
  406.             /* The routine to open the file would go here, and the */
  407.             /* file handle would be returned instead of NULL.        */
  408.             EndDialog(hDlg, hFile);
  409.             return (TRUE);
  410.  
  411.         case IDCANCEL:
  412.             EndDialog(hDlg, NULL);
  413.             return (FALSE);
  414.         }
  415.         break;
  416.  
  417.     case WM_INITDIALOG:               /* message: initialize    */
  418.         UpdateListBox(hDlg);
  419.         SetDlgItemText(hDlg, ID_FILETITLE, DialogTitle);
  420.         SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
  421.         SendDlgItemMessage(hDlg,           /* dialog handle     */
  422.         IDC_EDIT,               /* where to send message  */
  423.         EM_SETSEL,               /* select characters      */
  424.         NULL,                   /* additional information */
  425.         MAKELONG(0, 0x7fff));           /* entire contents       */
  426.         SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  427.         return (FALSE); /* Indicates the focus is set to a control */
  428.     }
  429.     return FALSE;
  430. }
  431.  
  432. /****************************************************************************
  433.  
  434.     FUNCTION: UpdateListBox(HWND);
  435.  
  436.     PURPOSE: Update the list box of OpenDlg
  437.  
  438. ****************************************************************************/
  439.  
  440. void UpdateListBox(hDlg)
  441. HWND hDlg;
  442. {
  443.     strcpy(str, DefPath);
  444.     strcat(str, DefSpec);
  445.     DlgDirList(hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010);
  446.  
  447.     /* To ensure that the listing is made for a subdir. of
  448.      * current drive dir...
  449.      */
  450.     if (!strchr (DefPath, ':'))
  451.     DlgDirList(hDlg, DefSpec, IDC_LISTBOX, IDC_PATH, 0x4010);
  452.  
  453.     /* Remove the '..' character from path if it exists, since this
  454.      * will make DlgDirList move us up an additional level in the tree
  455.      * when UpdateListBox() is called again.
  456.      */
  457.     if (strstr (DefPath, ".."))
  458.     DefPath[0] = '\0';
  459.  
  460.     SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
  461. }
  462.  
  463. /****************************************************************************
  464.  
  465.     FUNCTION: ChangeDefExt(PSTR, PSTR);
  466.  
  467.     PURPOSE: Change the default extension
  468.  
  469. ****************************************************************************/
  470.  
  471. void ChangeDefExt(Ext, Name)
  472. PSTR Ext, Name;
  473. {
  474.     PSTR pTptr;
  475.  
  476.     pTptr = Name;
  477.     while (*pTptr && *pTptr != '.')
  478.     pTptr++;
  479.     if (*pTptr)
  480.     if (!strchr(pTptr, '*') && !strchr(pTptr, '?'))
  481.         strcpy(Ext, pTptr);
  482. }
  483.  
  484. /****************************************************************************
  485.  
  486.     FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
  487.  
  488.     PURPOSE: Separate filename and pathname
  489.  
  490. ****************************************************************************/
  491.  
  492. void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
  493. HWND hDlg;
  494. LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
  495. {
  496.     LPSTR lpTmp;
  497.     char  cTmp;
  498.  
  499.     lpTmp = lpSrcFileName + (long) lstrlen(lpSrcFileName);
  500.     while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
  501.     lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
  502.     if (*lpTmp != ':' && *lpTmp != '\\') {
  503.     lstrcpy(lpDestFileName, lpSrcFileName);
  504.     lpDestPath[0] = 0;
  505.     return;
  506.     }
  507.     lstrcpy(lpDestFileName, lpTmp + 1);
  508.     cTmp = *(lpTmp + 1);
  509.     lstrcpy(lpDestPath, lpSrcFileName);
  510.      *(lpTmp + 1) = cTmp;
  511.     lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
  512. }
  513.  
  514. /****************************************************************************
  515.  
  516.     FUNCTION: AddExt(PSTR, PSTR);
  517.  
  518.     PURPOSE: Add default extension
  519.  
  520. ***************************************************************************/
  521.  
  522. void AddExt(Name, Ext)
  523. PSTR Name, Ext;
  524. {
  525.     PSTR pTptr;
  526.  
  527.     pTptr = Name;
  528.     while (*pTptr && *pTptr != '.')
  529.     pTptr++;
  530.     if (*pTptr != '.')
  531.     strcat(Name, Ext);
  532. }
  533.  
  534. /****************************************************************************
  535.  
  536.     FUNCTION: CheckFileName(HWND, PSTR, PSTR)
  537.  
  538.     PURPOSE: Check for wildcards, add extension if needed
  539.  
  540.     COMMENTS:
  541.  
  542.     Make sure you have a filename and that it does not contain any
  543.     wildcards.  If needed, add the default extension.  This function is
  544.     called whenever your application wants to save a file.
  545.  
  546. ****************************************************************************/
  547.  
  548. BOOL CheckFileName(hWnd, pDest, pSrc)
  549. HWND hWnd;
  550. PSTR pDest, pSrc;
  551. {
  552.     PSTR pTmp;
  553.  
  554.     if (!pSrc[0])
  555.     return (FALSE);           /* Indicates no filename was specified */
  556.  
  557.     pTmp = pSrc;
  558.     while (*pTmp) {            /* Searches the string for wildcards */
  559.     switch (*pTmp++) {
  560.         case '*':
  561.         case '?':
  562.         MessageBox(hWnd, "Wildcards not allowed.",
  563.             NULL, MB_OK | MB_ICONEXCLAMATION);
  564.         return (FALSE);
  565.     }
  566.     }
  567.  
  568.     AddExt(pSrc, DefExt);         /* Adds the default extension if needed */
  569.  
  570.     if (OpenFile(pSrc, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0) {
  571.     sprintf(str, "Replace existing %s?", pSrc);
  572.     if (MessageBox(hWnd, str, "SaveFile",
  573.         MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
  574.         return (FALSE);
  575.     }
  576.     strcpy(pDest, pSrc);
  577.     return (TRUE);
  578. }
  579.  
  580. /****************************************************************************
  581.  
  582.     FUNCTION: center_window(HWND, int, int)
  583.  
  584.     PURPOSE:  Center the specified window within client area of parent.
  585.           Works only with popups which all the ones we want seem to be.
  586.           This function should be called before first paint of window.
  587.  
  588. ****************************************************************************/
  589.  
  590. void center_window(HWND hchild, int xadj, int yadj)
  591. {
  592.     RECT crect,prect;
  593.     int i,cwidth,cheight;
  594.     POINT center;
  595.     GetWindowRect(hchild, &crect);
  596.     GetClientRect(hwnd, &prect);   /* main Fractint window */
  597.     cwidth  = crect.right - crect.left;
  598.     cheight = crect.bottom - crect.top;
  599.     center.x = (prect.right + prect.left) / 2;
  600.     center.y = (prect.bottom + prect.top) / 2;
  601.     ClientToScreen(hwnd, ¢er);
  602.     if ((center.x += xadj - (cwidth  / 2)) < 0) center.x = 0;
  603.     if ((center.y += yadj - (cheight / 2)) < 0) center.y = 0;
  604.     if ((i = GetSystemMetrics(SM_CXSCREEN) - cwidth ) < center.x) center.x = i;
  605.     if ((i = GetSystemMetrics(SM_CYSCREEN) - cheight) < center.y) center.y = i;
  606.     MoveWindow(hchild, center.x, center.y, cwidth, cheight, FALSE);
  607. }
  608.  
  609. void SaveBitmapFile(HWND hWnd, char *FullPathName)
  610. {
  611.    long TotalSize, Saved = 0, ImageSize, n;
  612.    BITMAPFILEHEADER FileHeader;
  613.    unsigned PalSize, BitCount;
  614.    unsigned BlockSize = 10240;
  615.    int hFile;
  616.    char Temp[128];
  617.    OFSTRUCT OfStruct;
  618.    HANDLE hPal;
  619.    RGBQUAD FAR *Pal;
  620.  
  621.    hFile = OpenFile(FullPathName, &OfStruct, OF_CREATE);
  622.    if(hFile == NULL)
  623.    {
  624. FileError:
  625.       wsprintf(Temp, "File I/O error while saving %s.", (LPSTR)FullPathName);
  626.       MessageBox(hWnd, Temp, "File Error . . .", MB_OK | MB_ICONEXCLAMATION);
  627.  
  628. GeneralError:
  629.       _lclose(hFile);
  630.       OpenFile(FullPathName, &OfStruct, OF_DELETE);
  631.       CloseStatusBox();
  632.       return;
  633.    }
  634.  
  635.    BitCount = pDibInfo->bmiHeader.biBitCount;
  636.    if(BitCount != 24)
  637.       PalSize = (1 << BitCount) * sizeof(RGBQUAD);
  638.    else
  639.       PalSize = 0;
  640.  
  641.    ImageSize = pDibInfo->bmiHeader.biSizeImage;
  642.    FileHeader.bfType = 0x4d42; /* 'BM'; */
  643.    FileHeader.bfSize = sizeof(FileHeader) +
  644.                        pDibInfo->bmiHeader.biSize +
  645.                        PalSize + ImageSize;
  646.    TotalSize = FileHeader.bfSize;
  647.    FileHeader.bfReserved1 = FileHeader.bfReserved2 = 0;
  648.    FileHeader.bfOffBits = FileHeader.bfSize - ImageSize;
  649.    Saved += _lwrite(hFile, (LPSTR)&FileHeader, sizeof(FileHeader));
  650.    Saved += _lwrite(hFile, (LPSTR)pDibInfo, (int)pDibInfo->bmiHeader.biSize);
  651.    if(PalSize)
  652.    {
  653.       hPal = GlobalAlloc(GMEM_FIXED, PalSize);
  654.       Pal = (RGBQUAD FAR *)GlobalLock(hPal);
  655.       if(Pal == NULL)
  656.       {
  657.          MessageBox(hWnd, "Insufficient Memory", "Memory Error . . .",
  658.                           MB_ICONEXCLAMATION | MB_OK);
  659.          goto GeneralError;
  660.       }
  661.       for(n = 0; n < (1 << BitCount); n++)
  662.       {
  663.          Pal[n].rgbRed   = pLogPal->palPalEntry[n].peRed;
  664.          Pal[n].rgbGreen = pLogPal->palPalEntry[n].peGreen;
  665.          Pal[n].rgbBlue  = pLogPal->palPalEntry[n].peBlue;
  666.          Pal[n].rgbReserved = 0;
  667.       }
  668.       Saved += _lwrite(hFile, (LPSTR)Pal, PalSize);
  669.       GlobalUnlock(hPal);
  670.       GlobalFree(hPal);
  671.    }
  672.    UpdateStatusBox(Saved, TotalSize);
  673.    keypressed();
  674.  
  675.    /* We should have saved enough bytes to reach the image offset.  If not,
  676.       then there was an error. */
  677.    if(Saved != FileHeader.bfOffBits)
  678.       goto FileError;
  679.  
  680.    for(n = 0; n < (ImageSize - BlockSize); n += BlockSize)
  681.    {
  682.       if(_lwrite(hFile, (LPSTR)&pixels[n], BlockSize) != BlockSize)
  683.          goto FileError;
  684.       Saved += BlockSize;
  685.       UpdateStatusBox(Saved, TotalSize);
  686.       keypressed();
  687.       if(OperCancelled)
  688.       {
  689.          MessageBox(hWnd, "File save cancelled.", "Save Cancelled", MB_OK);
  690.          goto GeneralError;
  691.       }
  692.    }
  693.    Saved += _lwrite(hFile, (LPSTR)&pixels[n], (int)(ImageSize - n));
  694.    if(Saved != TotalSize)
  695.       goto FileError;
  696.  
  697.    UpdateStatusBox(Saved, TotalSize);
  698.    _lclose(hFile);
  699.    CloseStatusBox();
  700. }
  701.